﻿using System;
using System.Collections.Generic;
using AdaptiveAgents.Agents;
using AdaptiveAgents.Loggers;
using AdaptiveAgents.Games;
using AdaptiveAgents.Distributions;
using System.Data;


namespace AdaptiveAgents.Experiments
{
    public class MultiGameExperiment : Experiment
    {
        private const string PATH = "..//..//";
        private List<DataSet> _games = null; //Represents game parameters for running
        List<string> _resultDataSetFiles = null;

        public MultiGameExperiment(List<DataSet> games)
            : base(0, 0, 0)
        {
            _games = games;
            _resultDataSetFiles = new List<string>(_games.Count);
        }

        public override void runExperiment()
        {
            int numGames = _games.Count;
            //DataSet dsExperimentResults = new DataSet("ExperimentsResults");
            int gameCounter = 0;

            foreach (DataSet ds in _games)
            {
                int numOfPlayers = (int)ds.Tables[0].Rows[0][0]; //Get num of players
                numRounds = (int)ds.Tables[0].Rows[0][2]; //Get num of rounds
                GameType type = (GameType)Enum.Parse(typeof(GameType), ds.Tables[0].Rows[0][1].ToString());

                // Set the environment
                Environment env = new Environment();

                #region Creating agents
                //Create a new population of players
                List<Agent> agents = new List<Agent>();
                int numOfAgents = ds.Tables[1].Rows.Count;

                AgentDirector director = new AgentDirector();
                for (int i = 0; i < numOfAgents; ++i)
                {

                    NormalBuilder builder = new NormalBuilder();  //HACK should support more than Normal type agent
                    director.Builder = builder;

                    director.construct(i, env,
                        double.Parse(ds.Tables[1].Rows[i][1].ToString()),
                        _logger);

                    Agent agent = director.getAgent();

                    //TODO add distribution to agent
                    //String strDist = ds.Tables[1].Rows[i][2].ToString();
                    //agent.Competence
                    agent.Competence = (IDistribution)ds.Tables[1].Rows[i][3];//new Distributions.Blocks();
                    env.addAgent(agent);
                }

                //Create Game Logger
                String stamp = DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss");
                String fileName = "MultiGame" + stamp + (gameCounter++) + ".xml";
                _logger = new XmlLogger(fileName);

                #endregion



                Game game = GameFactory.create(type, env, numRounds);
                
                double utility = game.start(_logger);
                _logger.Close();

                //Save the file name of the output of the logger
                _resultDataSetFiles.Add(fileName);

                utilitySum += utility;
                utilitySquaredSum += utility * utility;

                //Get the results table from game
                //DataSet dsGame = new DataSet("GameDataSet");
                //dsGame.ReadXml(fileName);

                
                //dsExperimentResults.Tables.Add(dsGame.Tables[0].Copy());
                //dsExperimentResults.Tables.Add(dsGame.Tables[1].Copy());
                //dsExperimentResults.Tables.Add(dsGame.Tables[2].Copy());
            }

            //Calculate statistics
            double avgUtility = utilitySum / numGames;
            double variance = 0, stdDev = 0;
            if (numGames > 1)
            {
                variance = (numGames * utilitySquaredSum - utilitySum * utilitySum)
                        / (numGames * (numGames - 1));
                stdDev = Math.Sqrt(variance);
            }
            
            //dsExperiment.
            
        }

        public List<String> ResultsFiles
        {
            get { return new List<string>(_resultDataSetFiles); }
        }
    }
}
